//BeanCipher - Bean Cipher Security Layer
//Copyright (C) 2005 Raul Alfredo Bajales
//
//This library is free software; you can redistribute it and/or
//modify it under the terms of the GNU Lesser General Public
//License as published by the Free Software Foundation; either
//version 2.1 of the License, or (at your option) any later version.
//
//This library is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
//Lesser General Public License for more details.
//
//You should have received a copy of the GNU Lesser General Public
//License along with this library; if not, write to the Free Software
//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package tests;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;

import junit.framework.TestCase;
import tests.model.Seller;
import tests.model.User;
import tests.model.more.Car;
import tests.model.more.Moto;
import tests.model.more.other.Sedan;
import ar.com.rab.beancipher.impl.BeanCipherFactory;
import ar.com.rab.beancipher.spi.IBeanCipher;
import ar.com.rab.beancipher.spi.IBeanCipherFactory;
import ar.com.rab.beancipher.spi.exceptions.BeanCipherException;

/**
 * Different tests showing how to cipher and decipher beans
 * 
 * @author Bajales Raul
 */
public class Cases extends TestCase {
    
    private IBeanCipher beanCipher;
    private static final String BEAN_CIPHER_PROPERTIES = "bean-cipher.properties";
    private static final String BEAN_MAPPING_FILE_NAME_KEY = "configuration.bean.mapping.file.name";
    private static final String REGISTRY_FILE_NAME_KEY = "configuration.registry.file.name";
    
    public Cases() throws BeanCipherException, FileNotFoundException, IOException {
        super();
        IBeanCipherFactory factory = new BeanCipherFactory();
        this.beanCipher = factory.create();
    }

    /**
     * @param fileName
     * @throws FileNotFoundException
     * @throws IOException
     */
    private void showFile(String fileName) throws FileNotFoundException, IOException {
        System.out.println("--> FILE: " + fileName);
        BufferedReader reader = new BufferedReader(new FileReader(new File(fileName)));
        String line = reader.readLine();
        while (line != null) {
            System.out.println(line);
            line = reader.readLine();
        }
        System.out.println();
    }
    
    /**
     * @throws FileNotFoundException
     * @throws IOException
     */
    public void testShowXMLs() throws FileNotFoundException, IOException {
        Properties properties = new Properties();
        properties.load(new FileInputStream(new File(BEAN_CIPHER_PROPERTIES)));
        showFile(properties.getProperty(BEAN_MAPPING_FILE_NAME_KEY));
        showFile(properties.getProperty(REGISTRY_FILE_NAME_KEY));
    }

    /**
     * This tests the maintain state feature: if a bean is
     * already ciphered and we try to cipher it again,
     * then BeanCipher does nothing (to avoid repeating cipherings).
     * Note: Idem for decipher case.
     * 
     * @throws BeanCipherException
     */
    public void testSimpleCipheringCheckingState() throws BeanCipherException {
        System.out.println("--> testSimpleCipheringCheckingState() - mapped class: tests.model.User");
        User user = new User("123", "John");
        System.out.println("ciphered:");
        this.beanCipher.cipherBean(user);
        this.beanCipher.cipherBean(user);
        System.out.println(user);
        assertNotSame("John", user.getName());
        System.out.println("deciphered:");
        this.beanCipher.deCipherBean(user);
        this.beanCipher.deCipherBean(user);
        System.out.println(user);
        assertEquals("John", user.getName());
        System.out.println("Test OK.");
    }
    
    /**
     * This tests demostrates that the mapping of a package
     * works properly.
     * Also demostrates that BeanCipher can determine
     * what PropertyCipher to apply on the input bean, even
     * if this is passed as Object.
     * 
     * @throws BeanCipherException
     */
    public void testMappedPackage() throws BeanCipherException {
        System.out.println("--> testMappedPackage() - mapped package: tests.model.more");
        List list = new ArrayList();
        Car car = new Car("red", "black");
        Moto moto = new Moto("Mike", "brown");
        list.add(car);
        list.add(moto);
        System.out.println("ciphereds:");
        for (Iterator iter = list.iterator(); iter.hasNext();) {
            Object element = (Object) iter.next();
            this.beanCipher.cipherBean(element);
            System.out.println(element);
        }        
        System.out.println("deciphereds:");
        for (Iterator iter = list.iterator(); iter.hasNext();) {
            Object element = (Object) iter.next();
            this.beanCipher.deCipherBean(element);
            System.out.println(element);
        }
        assertEquals(car.getColour(), "red");
        assertEquals(moto.getOwnerName(), "Mike");
        System.out.println("Test OK.");
    }
    
    /**
     * This tests demostrates ciphering / deciphering of composite objects where the components
     * are mapped to a different property cipher.
     * Also demostrates the ciphering using inherited properties.
     * 
     * @throws BeanCipherException
     */
    public void testUsingInheritedPropertiesAndComposition() throws BeanCipherException {
        System.out.println("--> testUsingInheritedPropertiesAndComposition() - mapped package: tests.model.more.other");
        Sedan sedan = new Sedan("red", "black", "Tony", new Integer(10), new Seller("Super Cars", "5th. avenue"));
        System.out.println("ciphered:");
        this.beanCipher.cipherBean(sedan);
        System.out.println(sedan);
        System.out.println("deciphered:");
        this.beanCipher.deCipherBean(sedan);
        System.out.println(sedan);
        assertEquals(sedan.getSeller().getCompanyName(), "Super Cars");
        System.out.println("Test OK.");
    }
}
